//nam_server.c
// 2013. 05. 27.
// Written by Nam
// CoreBASE 서버

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/epoll.h>
#include <time.h>
#include <signal.h>
#include "struct_acc_sago.h"
#include "struct_common_nam.h"

#define BUFSIZE 1024
#define EPOLL_SIZE 30

void get_current_time(time_t cur_t, char *buf);

int main(int argc, char const *argv[])
{
	struct sockaddr_in servaddr, clntaddr;
	struct epoll_event *events, ev;
	struct dn_event *ev_st;
	int sock_fd, epoll_fd, clnt_sock_fd;
	int addrlen = sizeof(servaddr);
	char timebuf[BUFSIZE];
	char buf[BUFSIZE];
	int i;
	time_t clnt_login_time, clnt_logout_time;

	struct queue_message msg;
	int msg_size = sizeof(msg)-sizeof(long);

	epoll_fd = epoll_create(EPOLL_SIZE);
	events = malloc(sizeof(struct epoll_event)*EPOLL_SIZE);
	sock_fd = socket(AF_INET, SOCK_STREAM, 0);
	servaddr.sin_addr.s_addr = inet_addr("192.168.172.137");
	servaddr.sin_port = htons(12333);
	servaddr.sin_family = AF_INET;
	signal(SIGINT, SIG_IGN);

	int mq_key = ftok("key", 2000);
	int mqid = msgget(mq_key, IPC_CREAT|0644);
	printf("메세지 큐(#%d)에 연결되었습니다\n", mqid);

	int sockopt = 1;
	setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
	bind(sock_fd, (struct sockaddr*)&servaddr, sizeof(servaddr));
	listen(sock_fd, 10);

	memset(&ev, 0, sizeof(ev));
	ev.data.fd = sock_fd;
	ev.events = EPOLLIN;

	epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock_fd, &ev);
	int n;
	while(1)
	{
		memset(buf, 0, BUFSIZE);
		n = epoll_wait(epoll_fd, events, 30, -1);
		for(i=0; i<n; i++)
		{
			if(events[i].data.fd == sock_fd)
			{
				clnt_sock_fd = accept(sock_fd, (struct sockaddr*)&clntaddr, &addrlen);
				ev_st = (struct dn_event*)malloc(sizeof(struct dn_event));
				time(&clnt_login_time);
				memset(ev_st, 0, sizeof(struct dn_event));
				ev_st->fd = clnt_sock_fd;
				ev_st->login_time = clnt_login_time;
				ev.events = EPOLLIN;
				ev.data.ptr = ev_st;
				epoll_ctl(epoll_fd, EPOLL_CTL_ADD, clnt_sock_fd, &ev);
				get_current_time(clnt_login_time, timebuf);
				printf("[%d] client connect (%s)\n", clnt_sock_fd, timebuf);
			}
			else
			{
				int readn = 0;
				struct dn_event *tmp = (struct dn_event *)(events[i].data.ptr);
				if((readn = read(tmp->fd, buf, BUFSIZE))<=0)
				{
					epoll_ctl(epoll_fd, EPOLL_CTL_DEL, tmp->fd, &events[i]);
					close(tmp->fd);
					time(&clnt_logout_time);
					get_current_time(clnt_logout_time, timebuf);
					printf("[%d] disconnect (%s)\n", tmp->fd, timebuf);
					free(tmp);
				}
				else
				{
					printf("-------------------\n");
					// printf("buf : %s\n", buf);
					// printf("-------------------\n");

					//check TRID
					if(strncmp(buf, "2001", 4)==0)
					{
						printf("2001 - 계좌 사고 관리\n");
						memset(&msg, 0, sizeof(msg));
						msg.mtype = 204;
						memcpy(msg.buf, buf, sizeof(msg.buf));
						msgsnd(mqid, &msg, msg_size, IPC_NOWAIT);

						memset(&msg, 0, sizeof(msg));
						msg.mtype=214;
						while(1)
						{
							msgrcv(mqid, &msg, msg_size, 214, 0);
							//if(strlen(msg.buf)==0) break;
							//printf("write buf : %s\nto : %d\n", msg.buf, tmp->fd);
							write(tmp->fd, msg.buf, BUFSIZE);
							if(strncmp(msg.buf+4, "99", 2)!=0 
								&& strncmp(msg.buf+4, "9T",2)!=0
								&& strncmp(msg.buf+4, "9A",2)!=0
								&& strncmp(msg.buf+4, "9S",2)!=0)
							{
								printf("done\n");
								break;
							}
						}
					}
					else if(strncmp(buf, "2002", 4)==0)
					{
						printf("2002 - 계좌 처분제한(압류)관리\n");
						memset(&msg, 0, sizeof(msg));
						msg.mtype = 204;
						memcpy(msg.buf, buf, sizeof(msg.buf));
						msgsnd(mqid, &msg, msg_size, IPC_NOWAIT);

						memset(&msg, 0, sizeof(msg));
						msg.mtype=214;
						while(1)
						{
							msgrcv(mqid, &msg, msg_size, 214, 0);
							//if(strlen(msg.buf)==0) break;
							//printf("write buf : %s\nto : %d\n", msg.buf, tmp->fd);
							write(tmp->fd, msg.buf, BUFSIZE);
							if(strncmp(msg.buf+4, "99", 2)!=0)
							{
								printf("done\n");
								break;
							}
						}
					}
					else if(strncmp(buf, "2003", 4)==0)
					{
						printf("2003 - 질권설정\n");
						memset(&msg, 0, sizeof(msg));
						msg.mtype = 204;
						memcpy(msg.buf, buf, sizeof(msg.buf));
						msgsnd(mqid, &msg, msg_size, IPC_NOWAIT);

						memset(&msg, 0, sizeof(msg));
						msg.mtype=214;
						msgrcv(mqid, &msg, msg_size, 214, 0);
						//printf("write buf : %s\nto : %d\n", msg.buf, tmp->fd);
						write(tmp->fd, msg.buf, BUFSIZE);
					}
					else if(strncmp(buf, "2004", 4)==0)
					{
						printf("2004 - 사고내역조회\n");
						memset(&msg, 0, sizeof(msg));
						msg.mtype = 204; //send-204, recv-214
						memcpy(msg.buf, buf, sizeof(msg.buf));
						msgsnd(mqid, &msg, msg_size, IPC_NOWAIT);

						memset(&msg, 0, sizeof(msg));
						msg.mtype=214;
						while(1)
						{
							msgrcv(mqid, &msg, msg_size, 214, 0);
							//if(strlen(msg.buf)==0) break;
							//printf("write buf : %s\nto : %d\n", msg.buf, tmp->fd);
							write(tmp->fd, msg.buf, BUFSIZE);
							if(strncmp(msg.buf+4, "99", 2)!=0 
								&& strncmp(msg.buf+4, "9T",2)!=0
								&& strncmp(msg.buf+4, "9A",2)!=0
								&& strncmp(msg.buf+4, "9S",2)!=0)
							{
								printf("done\n");
								break;
							}
						}
						//printf("write buf : %s\nto : %d\n", msg.buf, tmp->fd);
						write(tmp->fd, msg.buf, BUFSIZE);
						//sprintf(buf, "nam12345");
						//write(tmp->fd, buf, BUFSIZE);

					}
					else if(strncmp(buf, "2007", 4)==0)
					{
						printf("2007 - 주문 : 매수\n");
						memset(&msg, 0, sizeof(msg));
						msg.mtype = 207;
						memcpy(msg.buf, buf, sizeof(msg.buf));
						msgsnd(mqid, &msg, msg_size, IPC_NOWAIT);

						while(1)
						{
							msgrcv(mqid, &msg, msg_size, 217, 0);
							if(strncmp(msg.buf,"20079A",6)==0)
							{
								printf("내역전송\n");
								//printf("write buf : %s\nto : %d\n", msg.buf, tmp->fd);
								write(tmp->fd, msg.buf, BUFSIZE);
							}
							else
							{
								break;
							}
						}
						//printf("write buf : %s\nto : %d\n", msg.buf, tmp->fd);
						write(tmp->fd, msg.buf, BUFSIZE);
					}

					else if(strncmp(buf, "2222", 4)==0)
					{
						printf("2222-계좌or종목 조회\n");
						memset(&msg, 0, sizeof(msg));
						msg.mtype=222;
						memcpy(msg.buf, buf, sizeof(msg.buf));
						msgsnd(mqid, &msg, msg_size, IPC_NOWAIT);

						memset(&msg, 0, sizeof(msg));
						msg.mtype=223;
						msgrcv(mqid, &msg, msg_size, 223, 0);
						//printf("write buf : %s\nto : %d\n", msg.buf, tmp->fd);
						write(tmp->fd, msg.buf, BUFSIZE);
					}

				}
			}//else
		}//for
	}//while
	return 0;
}//main

void get_current_time(time_t cur_t, char *buf)
{
	struct tm* tmm;
	tmm = localtime(&cur_t);
	sprintf(buf, "%d/%d/%d %02d:%02d:%02d",tmm->tm_year+1900,tmm->tm_mon+1,tmm->tm_mday,tmm->tm_hour,tmm->tm_min,tmm->tm_sec);
}